package wsepForum.domain;

import java.io.IOException;
import java.util.Hashtable;

import jaxcentPlus.JaxcentLoggerListener;
import jaxcentServer.ServerMain;
import wsepForum.logging.ForumLogger;
import wsepForum.logging.ForumLogger.LoggerCategory;
import wsepForum.network.common.ConsoleToken;
import wsepForum.network.exception.ServerLoadException;
import wsepForum.network.server.*;
import wsepForum.network.server.gate.*;
import wsepForum.persistance.*;
/**
 * The backbone of the software, contains the start point the server
 * and inits all other parts.
 * @author Amir Harel & Ariel Rozen & Oren Ben-Haim
 *
 */
public class ForumDomain {

	/*****************************
	 * MEMBERS                   *
	 *****************************/
	/**
	 * The interface supplied by the persistent layer.
	 */
	protected IPersistentHandler persistent;

	/**
	 * The network server
	 */
	protected SimpleServer server;
	/**
	 * The UI controller
	 */
	private ConsoleUIContoller ui;

	/**
	 * the jaxcent server used to connect with web clients
	 */
	private ServerMain jaxcentServer;

	/*****************************
	 * CONSTRUCTOR               *
	 *****************************/
	/**
	 * @param args command line arguments
	 */
	public ForumDomain(String[] args){
		init();
	}

	/**
	 * Start point of the server, inits the server
	 * @param args command line arguments
	 */
	public static void main(String[] args) {
		new ForumDomain(args);
	}

	/*****************************
	 * METHODS                   *
	 *****************************/
	/**
	 * Inits server's domain parts
	 * @post session holder is initiated,
	 * persistance data handler is initiated,
	 * UI controller is initiated,
	 * network controller is initiated(and listening to the desired port)
	 */
	public void init() {
		try {

			// init database handler
			this.persistent = new DataHandler(new SQLConnector(), CompassSearchAdaptor.getInstance());
			this.persistent.initDB();

			SessionManager.getInstance().setPersistent(persistent);
			initJaxcent();
			// init swing server
			this.server = new SimpleServer(this,new GUIConnectionHandlerFactory(this,new ServerGUIController()),2323);
			this.server.start(); // starts the server
			ForumLogger.getInstance().info("Forum's core initiated", LoggerCategory.DOMAIN);
		} catch (Exception e) {
			ForumLogger.getInstance().error("Forum cannot initiate! "+e.getMessage(), LoggerCategory.DOMAIN);
		}
	}

	/**
	 * Close all forum's systems
	 */
	synchronized public void close() {
		try {
			// closing server's listen socket
			this.server.close();
			this.persistent.close();

			// TODO close database

			try { jaxcentServer.terminate(); } finally{};

			ForumLogger.getInstance().info("Forum's core closed manually", LoggerCategory.DOMAIN);
		} catch (IOException e) {
			ForumLogger.getInstance().error("Forum's core failed to close manually", LoggerCategory.DOMAIN);
		}
	}

	/**
	 *
	 */
	private void initJaxcent() throws ServerLoadException {
		try {
			JaxcentLoggerListener listener = new JaxcentLoggerListener() {
				@Override
				public void gotJaxcentLogMessage(String log) {
					ForumLogger.getInstance().debug("Jaxcent: " + log, LoggerCategory.DOMAIN);
				}
			};
			jaxcentServer = new ServerMain(80,".\\html\\", "jaxconfig.xml", null, listener );
			jaxcentServer.start();
			ForumLogger.getInstance().info("Jaxcent web server initiated", LoggerCategory.DOMAIN);
		} catch (IOException e) {
			throw new ServerLoadException("Failed to load jaxcent server! "+e.getMessage());
		}
	}

	/**
	 * @return persistent layer object
	 */
	public IPersistentHandler getPersistent(){
		return persistent;
	}

	/**
	 * @param persistent The interface supplied by the persistent layer.
	 */
	public void setPersistent(IPersistentHandler persistent) {
		this.persistent = persistent;
	}


	/**
	 * @return the ui controller
	 */
	public IUIController<ConsoleToken> getUi() {
		return ui;
	}


	/** TODO REMOVE THIS DELEGATION
	 * Creates new session and add it to map
	 * @return the new session
	 */
	public Session createNewSession() {
		return SessionManager.getInstance().createNewSession();
	}


	/** TODO: REMOVE THIS DELEGATION
	 * @return the sessionMap
	 */
	public Hashtable<Double, Session> getSessionMap() {
		return SessionManager.getInstance().getSessionMap();
	}
}